home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
544b.lha
/
4D Navigator
/
4d.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-06
|
57KB
|
2,334 lines
/* 4D Navigator ©1991, Jerry D. Hedden, All Rights Reserved
The 4D Navigator program, source code, documenation, and icon imagery are
freely redistributable, but may not be modified in any way, or used in part
or in whole without the express written consent of the author. Images
generated by the 4D Navigator program may be used for any purpose provided
credit is given to the program's author.
Jerry D. Hedden
28 Windemere Dr.
Sicklerville, NJ 08081
Phone: (609)629-3975
Email: Hedden@ESDSDF.DNet.GE.com
===========================================================================
This source code REQUIRES Aztec 'C' v3.6a. It probably cannot be handled
by any other compiler because of the assumed register usage within the
embedded assembly code. Make with the following:
as startup
cc +x3 -e500 -z10000 4d
ln -m -o "4D Navigator" startup.o 4d.o -lc
===========================================================================
The following copyright notice accompanied the source code for Palette
Requester which was used as a model for this program's Color and View
Parameter requesters.
Palette Requester -- (c) Copyright 1989 Jonathan Potter
This program is freely redistributable, although all rights to it remain
with the author. It may be used freely in any program as long as this
notice remains intact, however, if you do this, please mention the author
in the program. If you wish to use this in a commercial program of any
kind, you must register with a $15 donation.
Please send donations, bug reports, comments and suggestions to :
Jonathan Potter
3 William Street
Clarence Park 5034
South Australia
Australia
===========================================================================
History:
v1.00 - 10 Aug 1991
Initial release
**************************************************************************/
#include <intuition/intuition.h>
#define TIMING 0
#define DEBUG 0
/* corrects <exec/memory.h> long integer problems */
#define CLEARED_CHIP 0x00010002L
/* determines "grid spacing" */
#define INTERVAL 18 /* degrees */
#define SEGMENTS (360/INTERVAL)
#define ONE80 (SEGMENTS/2)
#define LATRNG ((SEGMENTS/4)-1)
#define NUM_GRID_PTS (long)(SEGMENTS*LATRNG*SEGMENTS)
/* circle constants */
#define PI (float)3.1415926535897932384626433832795
#define HALF_DEG (float)(PI/360.0)
/* rotation constants */
#define RESTART -1
#define STOPPED 0
#define TEN_DEGREES 20
#define NINETY_DEGREES 180
#define THREE_SIXTY 720
/* the 4 coordinates */
#define X 0L
#define Y 1L
#define Z 2L
#define W 3L
/* required libraries */
struct Library *IntuitionBase, *GfxBase, *MathBase, *MathTransBase,
*_OpenLibrary();
/* Motorola FFP math routines */
long SPFix(), SPCmp(), SPTst();
float SPFlt(), SPNeg(), SPAdd(), SPSub(), SPMul(), SPDiv();
float SPSincos(), SPAcos(), SPSqrt();
/* information for display and graphics */
#define WIDTH 656L
#define HEIGHT 430L
#define PLANES 3
#define PLANESIZE (long)((WIDTH>>3)*HEIGHT)
struct Screen *screen, *OpenScreen();
struct ViewPort *vp;
struct Window *window, *OpenWindow();
struct RastPort *rp;
struct IntuiMessage *_GetMsg();
PLANEPTR buffer1[PLANES], buffer2[PLANES];
struct NewScreen MyScreen = {
0,0, WIDTH,HEIGHT,PLANES, 0,1, HIRES|LACE,CUSTOMSCREEN,
NULL,(UBYTE *)"4D Navigator",NULL,NULL
};
struct NewWindow MyWindow = {
0,0, WIDTH,HEIGHT, 0,1, RAWKEY,
NOCAREREFRESH|BORDERLESS|ACTIVATE|SIMPLE_REFRESH|RMBTRAP,
NULL,NULL,NULL,NULL,NULL, WIDTH,HEIGHT, WIDTH,HEIGHT, CUSTOMSCREEN
};
/* colors */
#define BLACK 0L
#define WHITE 7L
UWORD ColorTables[3][1<<PLANES] = {
/* B/W RED GREEN R+G BLUE R+B G+B W/B */
{0x0000,0x0A00,0x0070,0x0A90,0x000A,0x0B0A,0x0079,0x0CCC},
{0x0FFF,0x0F00,0x00C0,0x0F90,0x000F,0x0C0E,0x00BA,0x0000},
/* used by color requester */
{0x0000,0x0A00,0x0070,0x0A90,0x000A,0x0B0A,0x0079,0x0CCC}
};
/* arrays for holding pre-computed, converted "floating point" values */
short *cos, *sin, *factor, *_AllocMem();
/* arrays for holding the "GRID" */
short *p4d, *e4d, *x4d, *p3d, *e3d, *x3d, *p2d, *e2d, *x2d;
/* indexing macro for grid points */
#define INDX(i,j,k) (((((i)*LATRNG)+(j))*SEGMENTS)+(k))
/* view parameters */
short FrontLimit = 0, BackLimit = 15000, ScaleFactor = 30;
/* point is out of range */
#define DONT_PLOT 32000
#asm
NO_PLOT equ 32000
#endasm
/* sets up the pre-computed, converted "floating point" arrays */
Initialize()
{
register long i;
register float tsin;
float tcos;
register float w;
register short *x, *y;
Countdown();
x = cos; y = sin;
for (i=0; i<720; i++) {
tsin = SPSincos(&tcos,SPMul(HALF_DEG,SPFlt(i)));
*(x++) = (SPTst(tcos) >= 0) ? SPFix(SPAdd(0.5,SPMul(tcos,8192.0))) :
SPFix(SPSub(0.5,SPMul(tcos,8192.0)));
*(y++) = (SPTst(tsin) >= 0) ? SPFix(SPAdd(0.5,SPMul(tsin,8192.0))) :
SPFix(SPSub(0.5,SPMul(tsin,8192.0)));
}
Countdown();
x = factor+1;
for (i=-8191; i<=8191; i++) {
if (!(i&0x000001FF)) Countdown();
w = SPDiv(8192.0,SPFlt(i));
*(x++) = SPFix(SPAdd(SPMul(SPDiv(SPSqrt(SPSub(SPMul(w,w),1.0)),
SPAcos(w)),128.0),0.5));
}
Countdown();
}
/* sets the "GRID" to the "starting position" */
initial_pos()
{
short plong,lat,elong;
register short regd4, regd5;
long ind;
register long ind1,ind2;
register short *pts = x4d;
ind = 0;
for (plong=0; plong<180; plong+=INTERVAL) {
e4d[ind+X] = p4d[ind+Z] = sin[plong*2];
e4d[ind+W] = p4d[ind+Y] = cos[plong*2];
e4d[ind+Y] = e4d[ind+Z] = p4d[ind+X] = p4d[ind+W] = 0;
e4d[ind+(ONE80*4+X)] = p4d[ind+(ONE80*4+Z)] = sin[(plong+180)*2];
e4d[ind+(ONE80*4+W)] = p4d[ind+(ONE80*4+Y)] = cos[(plong+180)*2];
e4d[ind+(ONE80*4+Y)] = e4d[ind+(ONE80*4+Z)] =
p4d[ind+(ONE80*4+X)] = p4d[ind+(ONE80*4+W)] = 0;
ind += 4;
for (lat=INTERVAL; lat<=(90-INTERVAL); lat+=INTERVAL) {
ind1 = INDX(plong/INTERVAL,(lat/INTERVAL)-1,0)*4;
ind2 = INDX((plong/INTERVAL)+ONE80,(lat/INTERVAL)-1,ONE80)*4;
for (elong=0; elong<180; elong+=INTERVAL) {
regd4 = cos[lat*2]; regd5 = sin[plong*2];
#asm
muls d4,d5
moveq #13,d4
asr.l d4,d5
#endasm
pts[ind1+X] = regd5; regd5 = (-regd5); pts[ind2+X] = regd5;
regd4 = sin[lat*2]; regd5 = cos[elong*2];
#asm
muls d4,d5
moveq #13,d4
asr.l d4,d5
#endasm
pts[ind1+Y] = regd5; regd5 = (-regd5); pts[ind2+Y] = regd5;
regd4 = sin[lat*2]; regd5 = sin[elong*2];
#asm
muls d4,d5
moveq #13,d4
asr.l d4,d5
#endasm
pts[ind1+Z] = regd5; regd5 = (-regd5); pts[ind2+Z] = regd5;
regd4 = cos[lat*2]; regd5 = cos[plong*2];
#asm
muls d4,d5
moveq #13,d4
asr.l d4,d5
#endasm
pts[ind1+W] = regd5; regd5 = (-regd5); pts[ind2+W] = regd5;
ind1+=4; ind2+=4;
}
ind1 = INDX(plong/INTERVAL,(lat/INTERVAL)-1,ONE80)*4;
ind2 = INDX((plong/INTERVAL)+ONE80,(lat/INTERVAL)-1,0)*4;
for (elong=180; elong<360; elong+=INTERVAL) {
regd4 = cos[lat*2]; regd5 = sin[plong*2];
#asm
muls d4,d5
moveq #13,d4
asr.l d4,d5
#endasm
pts[ind1+X] = regd5; regd5 = (-regd5); pts[ind2+X] = regd5;
regd4 = sin[lat*2]; regd5 = cos[elong*2];
#asm
muls d4,d5
moveq #13,d4
asr.l d4,d5
#endasm
pts[ind1+Y] = regd5; regd5 = (-regd5); pts[ind2+Y] = regd5;
regd4 = sin[lat*2]; regd5 = sin[elong*2];
#asm
muls d4,d5
moveq #13,d4
asr.l d4,d5
#endasm
pts[ind1+Z] = regd5; regd5 = (-regd5); pts[ind2+Z] = regd5;
regd4 = cos[lat*2]; regd5 = cos[plong*2];
#asm
muls d4,d5
moveq #13,d4
asr.l d4,d5
#endasm
pts[ind1+W] = regd5; regd5 = (-regd5); pts[ind2+W] = regd5;
ind1+=4; ind2+=4;
}
}
}
}
/* rotates the four-dimensional space */
rotate_4d(dir1,dir2,angle)
long dir1, dir2;
short angle;
{
short plong,lat,elong;
register short regd4, regd5, cangle, sangle;
short *p4d11, *p4d12, *p4d21, *p4d22;
short *e4d11, *e4d12, *e4d21, *e4d22;
register short *x4d11, *x4d12;
short *x4d21, *x4d22;
if (angle == RESTART) {
initial_pos();
return;
}
cangle = cos[angle]; sangle = sin[angle];
p4d11 = p4d + dir1;
p4d12 = p4d + dir2;
p4d21 = p4d + ONE80*4 + dir1;
p4d22 = p4d + ONE80*4 + dir2;
e4d11 = e4d + dir1;
e4d12 = e4d + dir2;
e4d21 = e4d + ONE80*4 + dir1;
e4d22 = e4d + ONE80*4 + dir2;
x4d11 = x4d + dir1;
x4d12 = x4d + dir2;
x4d21 = x4d + INDX(ONE80,0,-ONE80)*4 + dir1;
x4d22 = x4d + INDX(ONE80,0,-ONE80)*4 + dir2;
for (plong=0; plong++ < ONE80; ) {
regd4 = *p4d11; regd5 = *p4d12;
#asm
move.w d4,d0 ; d1' = d1*cos - d2*sin
muls d6,d0
move.w d5,d2
muls d7,d2
sub.l d2,d0
move.w d4,d1 ; d2' = d1*sin + d2*cos
muls d7,d1
move.w d5,d2
muls d6,d2
add.l d2,d1
moveq #13,d3 ; normalize
asr.l d3,d0
asr.l d3,d1
move.w d0,d4
move.w d1,d5
#endasm
*p4d11 = regd4; regd4 = (-regd4); *p4d21 = regd4;
*p4d12 = regd5; regd5 = (-regd5); *p4d22 = regd5;
p4d11+=4; p4d12+=4; p4d21+=4; p4d22+=4;
regd4 = *e4d11; regd5 = *e4d12;
#asm
move.w d4,d0
muls d6,d0
move.w d5,d2
muls d7,d2
sub.l d2,d0
move.w d4,d1
muls d7,d1
move.w d5,d2
muls d6,d2
add.l d2,d1
moveq #13,d3
asr.l d3,d0
asr.l d3,d1
move.w d0,d4
move.w d1,d5
#endasm
*e4d11 = regd4; regd4 = (-regd4); *e4d21 = regd4;
*e4d12 = regd5; regd5 = (-regd5); *e4d22 = regd5;
e4d11+=4; e4d12+=4; e4d21+=4; e4d22+=4;
for (lat=0; lat++ < LATRNG; ) {
x4d21 += (SEGMENTS*4); x4d22 += (SEGMENTS*4);
for (elong=0; elong++ < ONE80; ) {
regd4 = *x4d11; regd5 = *x4d12;
#asm
move.w d4,d0
muls d6,d0
move.w d5,d2
muls d7,d2
sub.l d2,d0
move.w d4,d1
muls d7,d1
move.w d5,d2
muls d6,d2
add.l d2,d1
moveq #13,d3
asr.l d3,d0
asr.l d3,d1
move.w d0,d4
move.w d1,d5
#endasm
*x4d11 = regd4; regd4 = (-regd4); *x4d21 = regd4;
*x4d12 = regd5; regd5 = (-regd5); *x4d22 = regd5;
x4d11+=4; x4d12+=4; x4d21+=4; x4d22+=4;
}
x4d21 -= (SEGMENTS*4); x4d22 -= (SEGMENTS*4);
for (elong=ONE80; elong++ < SEGMENTS; ) {
regd4 = *x4d11; regd5 = *x4d12;
#asm
move.w d4,d0
muls d6,d0
move.w d5,d2
muls d7,d2
sub.l d2,d0
move.w d4,d1
muls d7,d1
move.w d5,d2
muls d6,d2
add.l d2,d1
moveq #13,d3
asr.l d3,d0
asr.l d3,d1
move.w d0,d4
move.w d1,d5
#endasm
*x4d11 = regd4; regd4 = (-regd4); *x4d21 = regd4;
*x4d12 = regd5; regd5 = (-regd5); *x4d22 = regd5;
x4d11+=4; x4d12+=4; x4d21+=4; x4d22+=4;
}
}
}
}
/* maps the four-dimensional space into three dimensions */
map_to_3d()
{
register short regd4, regd5, regd6, regd7;
short wval;
short plong,lat,elong;
short *p4d1, *p3d1, *p3d2;
short *e4d1, *e3d1, *e3d2;
register short *x4d1;
short *x3d1;
register short *x3d2;
p4d1 = p4d; p3d1 = p3d; p3d2 = p3d + ONE80*3;
e4d1 = e4d; e3d1 = e3d; e3d2 = e3d + ONE80*3;
x4d1 = x4d; x3d1 = x3d; x3d2 = x3d + INDX(ONE80,0,-ONE80)*3;
for (plong=0; plong++ < ONE80; ) {
if ((wval = *(p4d1+W)) >= 8192) {
*(p4d1+W) = 8192;
*(p3d1+X) = *(p4d1+X); *(p3d1+Y) = *(p4d1+Y); *(p3d1+Z) = *(p4d1+Z);
*(p4d1+ONE80*4+W) = -8192;
*(p3d2+X) = DONT_PLOT; *(p3d2+Y) = *(p3d2+Z) = 0;
} else
if (wval <= -8192) {
*(p4d1+W) = -8192;
*(p3d1+X) = DONT_PLOT; *(p3d1+Y) = *(p3d1+Z) = 0;
*(p4d1+ONE80*4+W) = 8192;
*(p3d2+X) = (-(*(p4d1+X))); *(p3d2+Y) = (-(*(p4d1+Y)));
*(p3d2+Z) = (-(*(p4d1+Z)));
} else {
regd6 = factor[8192+wval]; regd7 = factor[8192-wval];
regd4 = *(p4d1+X);
#asm
dummy1: move.w d4,d5
neg.w d5
cmpi.w #1000,d6
blt.s 1$
move.w #NO_PLOT,d4
bra.s 2$
1$ muls d6,d4
asr.l #7,d4
cmpi.w #1000,d7
blt.s 2$
move.w #NO_PLOT,d5
bra.s 3$
2$ muls d7,d5
asr.l #7,d5
3$
#endasm
*(p3d1+X) = regd4; *(p3d2+X) = regd5;
regd4 = *(p4d1+Y);
#asm
move.w d4,d5
neg.w d5
muls d6,d4
muls d7,d5
asr.l #7,d4
asr.l #7,d5
#endasm
*(p3d1+Y) = regd4; *(p3d2+Y) = regd5;
regd4 = *(p4d1+Z);
#asm
move.w d4,d5
neg.w d5
muls d6,d4
muls d7,d5
asr.l #7,d4
asr.l #7,d5
#endasm
*(p3d1+Z) = regd4; *(p3d2+Z) = regd5;
}
p4d1+=4; p3d1+=3; p3d2+=3;
if ((wval = *(e4d1+W)) >= 8192) {
*(e4d1+W) = 8192;
*(e3d1+X) = *(e4d1+X); *(e3d1+Y) = *(e4d1+Y); *(e3d1+Z) = *(e4d1+Z);
*(e4d1+ONE80*4+W) = -8192;
*(e3d2+X) = DONT_PLOT; *(e3d2+Y) = *(e3d2+Z) = 0;
} else
if (wval <= -8192) {
*(e4d1+W) = -8192;
*(e3d1+X) = DONT_PLOT; *(e3d1+Y) = *(e3d1+Z) = 0;
*(e4d1+ONE80*4+W) = 8192;
*(e3d2+X) = (-(*(e4d1+X))); *(e3d2+Y) = (-(*(e4d1+Y)));
*(e3d2+Z) = (-(*(e4d1+Z)));
} else {
regd6 = factor[8192+wval]; regd7 = factor[8192-wval];
regd4 = *(e4d1+X);
#asm
dummy2: move.w d4,d5
neg.w d5
cmpi.w #1000,d6
blt.s 1$
move.w #NO_PLOT,d4
bra.s 2$
1$ muls d6,d4
asr.l #7,d4
cmpi.w #1000,d7
blt.s 2$
move.w #NO_PLOT,d5
bra.s 3$
2$ muls d7,d5
asr.l #7,d5
3$
#endasm
*(e3d1+X) = regd4; *(e3d2+X) = regd5;
regd4 = *(e4d1+Y);
#asm
move.w d4,d5
neg.w d5
muls d6,d4
muls d7,d5
asr.l #7,d4
asr.l #7,d5
#endasm
*(e3d1+Y) = regd4; *(e3d2+Y) = regd5;
regd4 = *(e4d1+Z);
#asm
move.w d4,d5
neg.w d5
muls d6,d4
muls d7,d5
asr.l #7,d4
asr.l #7,d5
#endasm
*(e3d1+Z) = regd4; *(e3d2+Z) = regd5;
}
e4d1+=4; e3d1+=3; e3d2+=3;
for (lat=0; lat++ < LATRNG; ) {
x3d2 += (SEGMENTS*3);
for (elong=0; elong++ < ONE80; ) {
if ((wval = *(x4d1+W)) >= 8192) {
*(x4d1+W) = 8192;
*(x3d1+X) = *(x4d1+X); *(x3d1+Y) = *(x4d1+Y); *(x3d1+Z) = *(x4d1+Z);
*(x4d1+INDX(ONE80,0,ONE80)*4+W) = -8192;
*(x3d2+X) = DONT_PLOT; *(x3d2+Y) = *(x3d2+Z) = 0;
} else
if (wval <= -8192) {
*(x4d1+W) = -8192;
*(x3d1+X) = DONT_PLOT; *(x3d1+Y) = *(x3d1+Z) = 0;
*(x4d1+INDX(ONE80,0,ONE80)*4+W) = 8192;
*(x3d2+X) = (-(*(x4d1+X))); *(x3d2+Y) = (-(*(x4d1+Y)));
*(x3d2+Z) = (-(*(x4d1+Z)));
} else {
regd6 = factor[8192+wval]; regd7 = factor[8192-wval];
regd4 = *(x4d1+X);
#asm
dummy3: move.w d4,d5
neg.w d5
cmpi.w #1000,d6
blt.s 1$
move.w #NO_PLOT,d4
bra.s 2$
1$ muls d6,d4
asr.l #7,d4
cmpi.w #1000,d7
blt.s 2$
move.w #NO_PLOT,d5
bra.s 3$
2$ muls d7,d5
asr.l #7,d5
3$
#endasm
*(x3d1+X) = regd4; *(x3d2+X) = regd5;
regd4 = *(x4d1+Y);
#asm
move.w d4,d5
neg.w d5
muls d6,d4
muls d7,d5
asr.l #7,d4
asr.l #7,d5
#endasm
*(x3d1+Y) = regd4; *(x3d2+Y) = regd5;
regd4 = *(x4d1+Z);
#asm
move.w d4,d5
neg.w d5
muls d6,d4
muls d7,d5
asr.l #7,d4
asr.l #7,d5
#endasm
*(x3d1+Z) = regd4; *(x3d2+Z) = regd5;
}
x4d1+=4; x3d1+=3; x3d2+=3;
}
x3d2 -= (SEGMENTS*3);
for (elong=ONE80; elong++ < SEGMENTS; ) {
if ((wval = *(x4d1+W)) >= 8192) {
*(x4d1+W) = 8192;
*(x3d1+X) = *(x4d1+X); *(x3d1+Y) = *(x4d1+Y); *(x3d1+Z) = *(x4d1+Z);
*(x4d1+INDX(ONE80,0,-ONE80)*4+W) = -8192;
*(x3d2+X) = DONT_PLOT; *(x3d2+Y) = *(x3d2+Z) = 0;
} else
if (wval <= -8192) {
*(x4d1+W) = -8192;
*(x3d1+X) = DONT_PLOT; *(x3d1+Y) = *(x3d1+Z) = 0;
*(x4d1+INDX(ONE80,0,-ONE80)*4+W) = 8192;
*(x3d2+X) = (-(*(x4d1+X))); *(x3d2+Y) = (-(*(x4d1+Y)));
*(x3d2+Z) = (-(*(x4d1+Z)));
} else {
regd6 = factor[8192+wval]; regd7 = factor[8192-wval];
regd4 = *(x4d1+X);
#asm
dummy4: move.w d4,d5
neg.w d5
cmpi.w #1000,d6
blt.s 1$
move.w #NO_PLOT,d4
bra.s 2$
1$ muls d6,d4
asr.l #7,d4
cmpi.w #1000,d7
blt.s 2$
move.w #NO_PLOT,d5
bra.s 3$
2$ muls d7,d5
asr.l #7,d5
3$
#endasm
*(x3d1+X) = regd4; *(x3d2+X) = regd5;
regd4 = *(x4d1+Y);
#asm
move.w d4,d5
neg.w d5
muls d6,d4
muls d7,d5
asr.l #7,d4
asr.l #7,d5
#endasm
*(x3d1+Y) = regd4; *(x3d2+Y) = regd5;
regd4 = *(x4d1+Z);
#asm
move.w d4,d5
neg.w d5
muls d6,d4
muls d7,d5
asr.l #7,d4
asr.l #7,d5
#endasm
*(x3d1+Z) = regd4; *(x3d2+Z) = regd5;
}
x4d1+=4; x3d1+=3; x3d2+=3;
}
}
}
}
/* maps the 3D space into coordinates for the screen */
map_to_screen()
{
register short scale = (-ScaleFactor), back = BackLimit, front = FrontLimit, temp;
short plong, lat, elong;
short *p3d1, *p2d1, *e3d1, *e2d1;
register short *x3d1, *x2d1;
p3d1 = p3d; p2d1 = p2d; e3d1 = e3d; e2d1 = e2d; x3d1 = x3d; x2d1 = x2d;
for (plong=0; plong++ < SEGMENTS; ) {
if ((temp=*(p3d1+X)) < front || temp > back)
*(p2d1+X) = DONT_PLOT;
else {
*(p2d1+X) = (WIDTH/2) + (*(p3d1+Y)/scale);
temp = *(p3d1+Z);
#asm
muls #7,d7 ; for aspect ratio
asr.l #3,d7
divs d4,d7 ; *(p2d1+Y) = (HEIGHT/2) + (*(p3d1+Z)/scale);
add.w #215,d7
#endasm
*(p2d1+Y) = temp;
}
p3d1+=3; p2d1+=2;
if ((temp=*(e3d1+X)) < front || temp > back)
*(e2d1+X) = DONT_PLOT;
else {
*(e2d1+X) = (WIDTH/2) + (*(e3d1+Y)/scale);
temp = *(e3d1+Z);
#asm
muls #7,d7 ; for aspect ratio
asr.l #3,d7
divs d4,d7 ; *(e2d1+Y) = (HEIGHT/2) + (*(e3d1+Z)/scale);
add.w #215,d7
#endasm
*(e2d1+Y) = temp;
}
e3d1+=3; e2d1+=2;
for (lat=0; lat++ < LATRNG; ) {
for (elong=0; elong++ < SEGMENTS; ) {
if ((temp=*(x3d1+X)) < front || temp > back)
*(x2d1+X) = DONT_PLOT;
else {
*(x2d1+X) = (WIDTH/2) + (*(x3d1+Y)/scale);
temp = *(x3d1+Z);
#asm
muls #7,d7 ; for aspect ratio
asr.l #3,d7
divs d4,d7 ; *(x2d1+Y) = (HEIGHT/2) + (*(x3d1+Z)/scale);
add.w #215,d7
#endasm
*(x2d1+Y) = temp;
}
x3d1+=3; x2d1+=2;
}
}
}
}
#define LEFT 1
#define RIGHT 2
#define TOP 4
#define BOTTOM 8
/* plots the "GRID" into the screen buffer */
plot_in_buffer()
{
short i, plong, lat, elong;
long index;
register long num;
short firstx, firsty, farfirst;
register short x, y;
short far1;
register short far2=0;
register short *toplot, *toget;
short plot_buf[(SEGMENTS+1)*2];
toplot = plot_buf;
SetBuffer();
/*** EQUATOR & POLAR RING ***/
for (i=0; i<2; i++) {
toget = (i==0) ? e2d: p2d;
num = 0; far1 = 0;
if ((firstx = toget[0]) != DONT_PLOT) {
toplot[0] = firstx; toplot[1] = firsty = toget[1]; num = 2;
if (firstx < 0)
far1 |= LEFT;
else if (firstx >= WIDTH)
far1 |= RIGHT;
if (firsty < 0)
far1 |= TOP;
else if (firsty >= HEIGHT)
far1 |= BOTTOM;
farfirst = far1;
}
for (elong=2; elong<SEGMENTS*2; elong+=2) {
if ((x = toget[elong]) != DONT_PLOT) {
y = toget[elong+1];
if (x < 0)
far2 |= LEFT;
else if (x >= WIDTH)
far2 |= RIGHT;
if (y < 0)
far2 |= TOP;
else if (y >= HEIGHT)
far2 |= BOTTOM;
if (far1 & far2) {
if (num >= 4) {
Move(rp,(long)toplot[0],(long)toplot[1]);
PolyDraw(rp,num>>1,toplot);
num = 2;
}
toplot[0] = x;
toplot[1] = y;
} else {
toplot[num++] = x;
toplot[num++] = y;
}
far1 = far2; far2 = 0;
} else {
if (num >= 4) {
Move(rp,(long)toplot[0],(long)toplot[1]);
PolyDraw(rp,num>>1,toplot);
}
num = 0; far1 = 0;
}
}
if (num >= 2) {
if (firstx != DONT_PLOT) {
if (!(far1 & farfirst)) {
toplot[num++] = firstx; toplot[num++] = firsty;
}
}
if (num >= 4) {
Move(rp,(long)toplot[0],(long)toplot[1]);
PolyDraw(rp,num>>1,toplot);
}
}
}
toget = x2d;
/*** CIRCUM-EQUATORIAL ***/
rp->Mask = 0xFC;
for (lat=0; lat<LATRNG; lat++) {
for (elong=0; elong<SEGMENTS; elong++) {
num = 0; far1 = 0;
index=INDX(0,lat,elong)*2;
if ((firstx = toget[index]) != DONT_PLOT) {
toplot[0] = firstx; toplot[1] = firsty = toget[index+1]; num = 2;
if (firstx < 0)
far1 |= LEFT;
else if (firstx >= WIDTH)
far1 |= RIGHT;
if (firsty < 0)
far1 |= TOP;
else if (firsty >= HEIGHT)
far1 |= BOTTOM;
farfirst = far1;
}
for (plong=2; plong<SEGMENTS*2; plong+=2) {
index += LATRNG*SEGMENTS*2;
if ((x = toget[index]) != DONT_PLOT) {
y = toget[index+1];
if (x < 0)
far2 |= LEFT;
else if (x >= WIDTH)
far2 |= RIGHT;
if (y < 0)
far2 |= TOP;
else if (y >= HEIGHT)
far2 |= BOTTOM;
if (far1 & far2) {
if (num >= 4) {
Move(rp,(long)toplot[0],(long)toplot[1]);
PolyDraw(rp,num>>1,toplot);
num = 2;
}
toplot[0] = x;
toplot[1] = y;
} else {
toplot[num++] = x;
toplot[num++] = y;
}
far1 = far2; far2 = 0;
} else {
if (num >= 4) {
Move(rp,(long)toplot[0],(long)toplot[1]);
PolyDraw(rp,num>>1,toplot);
}
num = 0; far1 = 0;
}
}
if (num >= 2) {
if (firstx != DONT_PLOT) {
if (!(far1 & farfirst)) {
toplot[num++] = firstx; toplot[num++] = firsty;
}
}
if (num >= 4) {
Move(rp,(long)toplot[0],(long)toplot[1]);
PolyDraw(rp,num>>1,toplot);
}
}
}
}
/*** CIRCUM-POLAR ***/
rp->Mask = 0xF9;
for (lat=0; lat<LATRNG; lat++) {
for (plong=0; plong<SEGMENTS; plong++) {
num = 0; far1 = 0;
index=INDX(plong,lat,0)*2;
if ((firstx = toget[index]) != DONT_PLOT) {
toplot[0] = firstx; toplot[1] = firsty = toget[index+1]; num = 2;
if (firstx < 0)
far1 |= LEFT;
else if (firstx >= WIDTH)
far1 |= RIGHT;
if (firsty < 0)
far1 |= TOP;
else if (firsty >= HEIGHT)
far1 |= BOTTOM;
farfirst = far1;
}
for (elong=2; elong<SEGMENTS*2; elong+=2) {
index += 2;
if ((x = toget[index]) != DONT_PLOT) {
y = toget[index+1];
if (x < 0)
far2 |= LEFT;
else if (x >= WIDTH)
far2 |= RIGHT;
if (y < 0)
far2 |= TOP;
else if (y >= HEIGHT)
far2 |= BOTTOM;
if (far1 & far2) {
if (num >= 4) {
Move(rp,(long)toplot[0],(long)toplot[1]);
PolyDraw(rp,num>>1,toplot);
num = 2;
}
toplot[0] = x;
toplot[1] = y;
} else {
toplot[num++] = x;
toplot[num++] = y;
}
far1 = far2; far2 = 0;
} else {
if (num >= 4) {
Move(rp,(long)toplot[0],(long)toplot[1]);
PolyDraw(rp,num>>1,toplot);
}
num = 0; far1 = 0;
}
}
if (num >= 2) {
if (firstx != DONT_PLOT) {
if (!(far1 & farfirst)) {
toplot[num++] = firstx; toplot[num++] = firsty;
}
}
if (num >= 4) {
Move(rp,(long)toplot[0],(long)toplot[1]);
PolyDraw(rp,num>>1,toplot);
}
}
}
}
/*** LONG LINES ***/
rp->Mask = 0xFA;
for (elong=0; elong<SEGMENTS; elong++) {
for (plong=0; plong<SEGMENTS; plong++) {
num = 0; far1 = 0;
if (!(elong&1))
if ((x = e2d[plong*2]) != DONT_PLOT) {
toplot[0] = x; y = toplot[1] = e2d[plong*2+1]; num=2;
if (x < 0)
far1 |= LEFT;
else if (x >= WIDTH)
far1 |= RIGHT;
if (y < 0)
far1 |= TOP;
else if (y >= HEIGHT)
far1 |= BOTTOM;
}
index=INDX(plong,0,elong)*2;
for (lat=0; lat<LATRNG; lat++) {
if ((x = toget[index]) != DONT_PLOT) {
y = toget[index+1];
if (x < 0)
far2 |= LEFT;
else if (x >= WIDTH)
far2 |= RIGHT;
if (y < 0)
far2 |= TOP;
else if (y >= HEIGHT)
far2 |= BOTTOM;
if (far1 & far2) {
if (num >= 4) {
Move(rp,(long)toplot[0],(long)toplot[1]);
PolyDraw(rp,num>>1,toplot);
num = 2;
}
toplot[0] = x;
toplot[1] = y;
} else {
toplot[num++] = x;
toplot[num++] = y;
}
far1 = far2; far2 = 0;
} else {
if (num >= 4) {
Move(rp,(long)toplot[0],(long)toplot[1]);
PolyDraw(rp,num>>1,toplot);
}
num = 0; far1 = 0;
}
index += SEGMENTS*2;
}
if (num >= 2) {
if (!(plong&1))
if ((x = p2d[elong*2]) != DONT_PLOT) {
y = p2d[elong*2+1];
if (x < 0)
far2 |= LEFT;
else if (x >= WIDTH)
far2 |= RIGHT;
if (y < 0)
far2 |= TOP;
else if (y >= HEIGHT)
far2 |= BOTTOM;
if (!(far1 & far2)) {
toplot[num++] = x; toplot[num++] = y;
}
far2 = 0;
}
if (num >= 4) {
Move(rp,(long)toplot[0],(long)toplot[1]);
PolyDraw(rp,num>>1,toplot);
}
}
}
}
rp->Mask = 0xFF;
DisplayBuffer();
}
/* for double buffering */
SetBuffer()
{
register long i;
if (rp->BitMap->Planes[0] == buffer1[0])
for (i=0; i<PLANES; i++)
rp->BitMap->Planes[i] = buffer2[i];
else
for (i=0; i<PLANES; i++)
rp->BitMap->Planes[i] = buffer1[i];
SetRast(rp,BLACK);
}
DisplayBuffer()
{
WaitBOVP(vp);
WaitTOF();
ScrollVPort(vp);
RethinkDisplay();
}
#define ONE_KEY 1
#define ZERO_KEY 10
#define ESCAPE 69
#define SPACE 64
#define RKEY 19
#define TKEY 20
#define XKEY 50
#define CKEY 51
#define VKEY 52
#define KP8 62
#define KP2 30
#define KP4 45
#define KP6 47
#define LEFTARROW 79
#define RIGHTARROW 78
#define UPARROW 76
#define DOWNARROW 77
#define HELP 95
#if DEBUG
#define DKEY 34
#endif
#define TRANSLATE 1
#define ROTATE 0
MainLoop()
{
register struct IntuiMessage *msg;
register ULONG class;
register USHORT code, qualifier;
short mode, amount, step_rate;
long fromdir, toward;
short ColorSet = BLACK;
#if TIMING
long starttime[3],endtime[3];
#endif
Initialize();
mode = TRANSLATE; fromdir = X; toward = W; amount = RESTART, step_rate = 10;
FOREVER {
if (amount == STOPPED) {
_WaitPort(window->UserPort);
} else {
#if TIMING
DateStamp(starttime);
#endif
rotate_4d(fromdir,toward,amount);
map_to_3d();
map_to_screen();
plot_in_buffer();
#if TIMING
DateStamp(endtime);
PrintTime("Frame time",starttime,endtime);
#endif
if (amount != step_rate && amount != THREE_SIXTY-step_rate)
amount = STOPPED;
}
while (msg = _GetMsg(window->UserPort)) {
class = msg->Class; code = msg->Code; qualifier = msg->Qualifier;
_ReplyMsg(msg);
if (class == RAWKEY) {
switch (code) {
#if DEBUG
case DKEY:
if (qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
dump_coordinates(0); /* only plotted points */
else if (qualifier & (IEQUALIFIER_LALT|IEQUALIFIER_RALT))
dump_coordinates(1); /* all points */
else
dump_screen_plot();
break;
#endif
case RKEY:
case TKEY:
mode = (code == TKEY);
break;
case XKEY:
mode = TRANSLATE; fromdir = X; toward = W; amount = RESTART;
break;
case CKEY:
if (qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) {
ColorRequester(ColorSet);
if (amount == STOPPED) plot_in_buffer();
} else {
ColorSet = 1 - ColorSet;
LoadRGB4(vp, &ColorTables[ColorSet][0], 1L<<PLANES);
}
break;
case VKEY:
ViewRequester();
if (amount == STOPPED) {
map_to_screen();
plot_in_buffer();
}
break;
case SPACE: amount = STOPPED; break;
case KP4:
case KP6:
fromdir = Y; toward = (mode) ? W : X;
goto calc_amount;
case KP8:
case KP2:
fromdir = Z; toward = (mode) ? W : X;
goto calc_amount;
case LEFTARROW:
case RIGHTARROW:
mode = ROTATE; fromdir = Z; toward = Y;
goto calc_amount;
case UPARROW:
case DOWNARROW:
mode = TRANSLATE; fromdir = X; toward = W;
calc_amount:
if (qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
amount = TEN_DEGREES;
else if (qualifier & IEQUALIFIER_CONTROL)
amount = NINETY_DEGREES;
else
amount = step_rate;
if (code == KP2 || code == LEFTARROW ||
code == KP6 || code == DOWNARROW)
amount = THREE_SIXTY - amount;
break;
case ESCAPE:
cleanup(0L);
case HELP:
LoadRGB4(vp, &ColorTables[0][0], 1L<<PLANES);
info();
LoadRGB4(vp, &ColorTables[ColorSet][0], 1L<<PLANES);
if (amount == STOPPED) plot_in_buffer();
break;
default:
if (code >= ONE_KEY && code <= ZERO_KEY) {
if (amount != STOPPED)
if (amount == step_rate)
amount = code;
else
amount = THREE_SIXTY - code;
step_rate = code;
}
}
}
}
}
}
main()
{
long i;
if (IntuitionBase = _OpenLibrary("intuition.library", 0L))
if (GfxBase = _OpenLibrary("graphics.library", 0L))
if (MathBase = _OpenLibrary("mathffp.library", 0L))
if (MathTransBase = _OpenLibrary("mathtrans.library", 0L))
if (p4d = _AllocMem((long)(SEGMENTS*8),0L))
if (e4d = _AllocMem((long)(SEGMENTS*8),0L))
if (x4d = _AllocMem((long)(NUM_GRID_PTS*8L),0L))
if (p3d = _AllocMem((long)(SEGMENTS*6),0L))
if (e3d = _AllocMem((long)(SEGMENTS*6),0L))
if (x3d = _AllocMem((long)(NUM_GRID_PTS*6L),0L))
if (p2d = _AllocMem((long)(SEGMENTS*4),0L))
if (e2d = _AllocMem((long)(SEGMENTS*4),0L))
if (x2d = _AllocMem((long)(NUM_GRID_PTS*4L),0L))
if (cos = _AllocMem(1440L,0L))
if (sin = _AllocMem(1440L,0L))
if (factor = _AllocMem(32768L,0L))
if (screen = OpenScreen(&MyScreen)) {
vp = &screen->ViewPort;
LoadRGB4(vp,&ColorTables[0][0],1L<<PLANES);
MyWindow.Screen = screen;
if (window = OpenWindow(&MyWindow)) {
rp = window->RPort;
SetDrMd(rp,(long)JAM1);
SetAPen(rp,WHITE);
for (i=0; i<PLANES; i++) {
buffer1[i] = rp->BitMap->Planes[i];
if (!(buffer2[i] = (PLANEPTR)_AllocMem(PLANESIZE,CLEARED_CHIP)))
cleanup(101L);
}
MainLoop(); /* terminates via cleanup() */
}
}
cleanup(100L); /* no direct indication of what went wrong above */
}
cleanup(code)
long code;
{
long i;
if (p4d) _FreeMem(p4d,(long)(SEGMENTS*8));
if (e4d) _FreeMem(e4d,(long)(SEGMENTS*8));
if (x4d) _FreeMem(x4d,(long)(NUM_GRID_PTS*8L));
if (p3d) _FreeMem(p3d,(long)((long)SEGMENTS*6L));
if (e3d) _FreeMem(e3d,(long)((long)SEGMENTS*6L));
if (x3d) _FreeMem(x3d,(long)(NUM_GRID_PTS*6L));
if (p2d) _FreeMem(p2d,(long)((long)SEGMENTS*4L));
if (e2d) _FreeMem(e2d,(long)((long)SEGMENTS*4L));
if (x2d) _FreeMem(x2d,(long)(NUM_GRID_PTS*4L));
if (cos) _FreeMem(cos,1440L);
if (sin) _FreeMem(sin,1440L);
if (factor) _FreeMem(factor,32768L);
if (window) {
if (rp->BitMap->Planes[0] == buffer2[0]) {
SetBuffer();
DisplayBuffer();
}
CloseWindow(window);
}
for (i=0; i<PLANES; i++)
if (buffer2[i]) _FreeMem(buffer2[i],PLANESIZE);
if (screen) CloseScreen(screen);
if (MathTransBase) _CloseLibrary(MathTransBase);
if (MathBase) _CloseLibrary(MathBase);
if (GfxBase) _CloseLibrary(GfxBase);
if (IntuitionBase) _CloseLibrary(IntuitionBase);
exit(code);
}
#define X0 0L
#define X1 20L
#define X2 65L
#define X3 85L
#define Y0 0L
#define Y1 20L
#define Y2 60L
#define Y3 80L
#define Y4 120L
#define Y5 140L
Digit(n,x,y)
short n;
long x,y;
{
/* first a white rectangle */
RectFill(rp,x+X0,y+Y0,x+X3,y+Y5);
/* then "cut out" the appropriate parts */
SetAPen(rp,BLACK);
switch (n) {
case 0: RectFill(rp,x+X1,y+Y1,x+X2,y+Y4); return;
case 1: RectFill(rp,x+X0,y+Y0,x+X2,y+Y5); return;
case 2:
case 3: RectFill(rp,x+X0,y+Y1,x+X2,y+Y2); break; /* upper section */
case 4: RectFill(rp,x+X1,y+Y0,x+X2,y+Y2);
RectFill(rp,x+X0,y+Y3,x+X2,y+Y5); return;
case 5:
case 6: RectFill(rp,x+X1,y+Y1,x+X3,y+Y2); break; /* upper section */
case 7: RectFill(rp,x+X0,y+Y1,x+X2,y+Y5); return;
case 8:
case 9: RectFill(rp,x+X1,y+Y1,x+X2,y+Y2); /* upper section */
}
/* lower sections */
if (n==2)
RectFill(rp,x+X1,y+Y3,x+X3,y+Y4);
else if (n==3 || n==5 || n==9)
RectFill(rp,x+X0,y+Y3,x+X2,y+Y4);
else /* n==6 || n==8 */
RectFill(rp,x+X1,y+Y3,x+X2,y+Y4);
}
#define TENS_X 225L
#define ONES_X 340L
#define DIGITY 115L
Countdown()
{
static short _counter = 33;
SetBuffer();
Digit(_counter/10,TENS_X,DIGITY);
SetAPen(rp,WHITE);
Digit(_counter%10,ONES_X,DIGITY);
SetAPen(rp,WHITE);
DisplayBuffer();
_counter--;
}
/*** Info function ***/
struct TextAttr InfoFont =
{(UBYTE *)"topaz.font",8,FS_NORMAL,FPF_ROMFONT|FPF_DESIGNED};
struct IntuiText Text = {6,0,JAM2,0,0,&InfoFont,NULL,NULL};
#define TEXT_MARGIN 20L
#define TEXT_START 25L
char *InfoTitle =
" 4D Navigator v1.00 \2511991, Jerry D. Hedden, All Rights Reserved";
char *InfoText[] = {
"You are embedded within the three-dimensional 'surface' of a four-dimensional",
"sphere. Your initial position is on the equator looking east. The 'north",
"pole' of the polar ring is to your left. Pressing 'x' will reset you back to",
"this initial position. To quit, press 'esc'.",
"",
"You can move (translate) or turn (rotate) using the arrow- and keypad keys.",
"The up/down arrows send you moving forward/backward; the left/right arrows",
"rotate you clockwise/counterclockwise. The keypad 8, 2, 4 and 6 represent",
"the up, down, left and right directions. Pressing 't' sets translate mode",
"such that the keypad moves you in the appropriated directions; 'r' set rotate",
"mode so you can turn. Pressing an arrow-/keypad key alone causes its action",
"to repeat continuously. Press 'space' to stop. The change between frames",
"can be set from 0.5\260 to 5\260 using the keyboard 1 thru 0. 'Shift-' arrow-/",
"keypad keys cause a single 10\260 change; 'ctrl-' causes a 90\260 change.",
"",
"The view of your three-dimensional space is controlled by three parameters --",
"the scaling factor, the front cutoff, and the rear cutoff. The first con-",
"trols the width/height of your view; the other two control its depth. Press",
"'v' to bring up a requester to change these values. N.B. Your view of the",
"space is mapped to the screen without perspective.",
"",
"The coordinate system is: Latitude (LAT) -- the angular distance between the",
"equator (0\260) and the polar ring (90\260); Polar Longitude (PLONG) -- the angular",
"direction around the polar ring (0\260 - 360\260); and Equatorial Longitude (ELONG)",
"-- the angular direction around the equator (0\260 - 360\260). This is an extrap-",
"olation into three dimensions of latitude and longitude as used on the earth.",
"",
"The two white 'circles' are the equator and the polar ring. Green 'longi-",
"tude' lines run between them -- connecting points with the same PLONG and",
"ELONG. Red connects points with the same LAT and PLONG, and blue connects",
"points with the same LAT and ELONG.",
"",
"Press 'c' to toggle between two color sets (the 'white' set is intended for",
"printing). 'Shift-c' brings up a color requester.",
"",
"The 4D Navigator source code is a combination of 'C' and assembly using Manx",
"Aztec 'C' v3.6a. The source contains examples of double-buffering, fixed-",
"and floating-point math, and in-line assembly code. I also used some of the",
"code from Jonathan Potter's color requester. Send $5.00 to obtain a disk",
"containing source code and updated program.",
"",
" Comments, questions, bug reports, source requests:",
"",
" Jerry D. Hedden",
" 28 Windemere Dr.",
" Sicklerville, NJ 08081",
" Phone: (609)629-3975",
" Email: Hedden@ESDSDF.DNet.GE.com",
NULL
};
info()
{
register long line;
register struct Window *info_window;
register struct IntuiMessage *msg;
register ULONG class;
register short all_done;
MyWindow.IDCMPFlags = CLOSEWINDOW;
MyWindow.Flags = SIMPLE_REFRESH|NOCAREREFRESH|ACTIVATE|WINDOWCLOSE;
MyWindow.Title = (UBYTE *)InfoTitle;
if (!(info_window = OpenWindow(&MyWindow))) return;
for (line = 0; Text.IText = (UBYTE *)InfoText[line]; line++)
PrintIText(info_window->RPort,&Text,TEXT_MARGIN,TEXT_START+(line<<3));
for (all_done=0; !all_done; ) {
_WaitPort(info_window->UserPort);
while (msg = _GetMsg(info_window->UserPort)) {
class = msg->Class;
_ReplyMsg(msg);
if (class == CLOSEWINDOW) all_done = 1;
}
}
CloseWindow(info_window);
}
/*** common requester stuff ***/
#define RESET 41
#define CANCEL 42
#define OKAY 43
short border_xy[] = {0,0, 115,0, 115,10, 0,10, 0,0};
struct Border MyBorder = {-1,-1,4,0,JAM1,5,border_xy,NULL};
struct IntuiText
OkayText = {2,0,JAM1, 41,1,NULL,(UBYTE *)"OKAY", NULL},
ResetText = {3,0,JAM1, 37,1,NULL,(UBYTE *)"RESET", NULL},
CancelText = {1,0,JAM1, 33,1,NULL,(UBYTE *)"CANCEL",NULL};
struct Image PropImage1, PropImage2, PropImage3;
struct Window *ReqWindow;
/*** Color Requester ***/
#define RED 31
#define GREEN 32
#define BLUE 33
struct IntuiText
RedText = {1,0,JAM1,-14,2,NULL,(UBYTE *)"R",NULL},
GreenText = {2,0,JAM1,-14,2,NULL,(UBYTE *)"G",NULL},
BlueText = {4,0,JAM1,-14,2,NULL,(UBYTE *)"B",NULL},
ValuesText = {0,1,JAM2, 0,0,NULL,(UBYTE *)"RGB",NULL};
struct PropInfo
RedProp = {AUTOKNOB|FREEHORIZ,0,0,0x1000},
GreenProp = {AUTOKNOB|FREEHORIZ,0,0,0x1000},
BlueProp = {AUTOKNOB|FREEHORIZ,0,0,0x1000};
struct Image CurColorImage = {0,0,235,8,1,NULL,0,1,NULL};
struct Gadget
RedCGadg = {NULL,24,54,100,11,
GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET,
(APTR)&PropImage1,NULL,&RedText,NULL,(APTR)&RedProp,RED,NULL},
GreenCGadg = {&RedCGadg,24,66,100,11,
GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET,
(APTR)&PropImage2,NULL,&GreenText,NULL,(APTR)&GreenProp,GREEN,NULL},
BlueCGadg = {&GreenCGadg,24,78,100,11,
GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET,
(APTR)&PropImage3,NULL,&BlueText,NULL,(APTR)&BlueProp,BLUE,NULL},
OkayCGadg = {&BlueCGadg,130,79,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET,
(APTR)&MyBorder,NULL,&OkayText,NULL,NULL,OKAY,NULL},
ResetCGadg = {&OkayCGadg,130,67,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET,
(APTR)&MyBorder,NULL,&ResetText,NULL,NULL,RESET,NULL},
CancelCGadg = {&ResetCGadg,130,55,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET,
(APTR)&MyBorder,NULL,&CancelText,NULL,NULL,CANCEL,NULL};
struct NewWindow ColorNewWindow={
40,23,255,93,1,4,GADGETUP|GADGETDOWN|MOUSEBUTTONS|RAWKEY,
ACTIVATE|SIMPLE_REFRESH|NOCAREREFRESH|RMBTRAP,
&CancelCGadg,NULL,(UBYTE *)" 4D Navigator Color Requester",
NULL,NULL,0,0,0,0,CUSTOMSCREEN};
long CurColor;
ColorRequester(ColorSet)
short ColorSet;
{
register long i;
register ULONG Class;
register USHORT Code, GadgetID;
register struct IntuiMessage *msg;
ColorNewWindow.Screen = screen;
if (!(ReqWindow = OpenWindow(&ColorNewWindow))) return;
for (i=0; i < (1<<PLANES); i++)
ColorTables[2][i] = ColorTables[ColorSet][i];
DrawPalette(PLANES);
CurColorImage.PlaneOnOff = CurColor = 1;
ValuesText.FrontPen = CurColor^((1<<PLANES)-1);
ValuesText.BackPen = 1;
DrawImage(ReqWindow->RPort,&CurColorImage,10L,45L);
SetRGBProps();
FOREVER {
_WaitPort(ReqWindow->UserPort);
while (msg = _GetMsg(ReqWindow->UserPort)) {
Class = msg->Class; Code = msg->Code;
if (Class == GADGETUP || Class == GADGETDOWN)
GadgetID = ((struct Gadget *)msg->IAddress)->GadgetID;
_ReplyMsg(msg);
switch (Class) {
case MOUSEBUTTONS: {
long x,y;
long NewColor, ReadPixel();
if (Code != SELECTDOWN) break;
x=ReqWindow->MouseX; y=ReqWindow->MouseY;
if (x<12 || x>243 || y<15 || y>40) break;
if (CurColor == (NewColor = ReadPixel(ReqWindow->RPort,x,y))) break;
CurColorImage.PlaneOnOff = CurColor = NewColor;
DrawImage(ReqWindow->RPort,&CurColorImage,10L,45L);
SetRGBProps();
break;
}
case GADGETDOWN:
if (GadgetID >= RED && GadgetID <= BLUE) {
do {
ReadRGBProps();
} while (!(msg = _GetMsg(ReqWindow->UserPort)));
_ReplyMsg(msg);
ReadRGBProps();
}
break;
case RAWKEY:
if (Code != ESCAPE) break;
GadgetID = RESET;
case GADGETUP:
switch (GadgetID) {
case RESET:
for (i=0; i < (1<<PLANES); i++)
ColorTables[2][i] = ColorTables[ColorSet][i];
LoadRGB4(vp, &ColorTables[2][0], 1L<<PLANES);
SetRGBProps();
break;
case OKAY:
for (i=0; i < (1<<PLANES); i++)
ColorTables[ColorSet][i] = ColorTables[2][i];
case CANCEL:
LoadRGB4(vp, &ColorTables[ColorSet][0], 1L<<PLANES);
while (msg = _GetMsg(ReqWindow->UserPort)) _ReplyMsg(msg);
CloseWindow(ReqWindow);
return;
}
}
}
}
}
SetRGBProps()
{
register UWORD cval = ColorTables[2][CurColor];
NewModifyProp(&RedCGadg, ReqWindow,0L,(long)(FREEHORIZ|AUTOKNOB),
(long)(((cval>>8)&0xf)*0x1111),0L,0x1000L,0L,1L);
NewModifyProp(&GreenCGadg,ReqWindow,0L,(long)(FREEHORIZ|AUTOKNOB),
(long)(((cval>>4)&0xf)*0x1111),0L,0x1000L,0L,1L);
NewModifyProp(&BlueCGadg, ReqWindow,0L,(long)(FREEHORIZ|AUTOKNOB),
(long)((cval&0xf)*0x1111),0L,0x1000L,0L,1L);
ShowRGBValues();
}
ReadRGBProps()
{
register long re,gr,bl;
re = RedProp. HorizPot >> 12;
gr = GreenProp.HorizPot >> 12;
bl = BlueProp. HorizPot >> 12;
ColorTables[2][CurColor] = (re<<8)|(gr<<4)|bl;
SetRGB4(vp,CurColor,re,gr,bl);
ShowRGBValues();
}
char *hex = "0123456789ABCDEF";
ShowRGBValues()
{
register UWORD cval = ColorTables[2][CurColor];
ValuesText.IText[0] = hex[(cval>>8)&0xf];
ValuesText.IText[1] = hex[(cval>>4)&0xf];
ValuesText.IText[2] = hex[ cval &0xf];
ValuesText.FrontPen = CurColor^((1<<PLANES)-1);
ValuesText.BackPen = CurColor;
PrintIText(ReqWindow->RPort,&ValuesText,115L,45L);
}
DrawPalette(depth)
int depth;
{
long w,h,ox,x,y,i;
#if PLANES>3
if (depth==4)
{ w=29; h=12; ox=13; }
else if (depth==5)
{ w=14; h=12; ox=17; }
else
#endif
{ w=235/(1<<depth); h=25; ox=12; }
i=0; x=ox; y=15;
for (i=0; i<(1<<depth); i++) {
SetAPen(ReqWindow->RPort,i);
RectFill(ReqWindow->RPort,x,y,x+w,y+h);
#if PLANES>3
if (depth>3 && i==(1<<(depth-1))-1) {
x=ox; y+=h;
} else
#endif
x+=w;
}
}
/*** View Requester ***/
#define FRONT 31
#define BACK 32
#define SCALE 33
#define TEXTX 5L
#define TEXTY -10L
#define GADGX 8L
#define FGADY 25L
#define BGADY 50L
#define SGADY 75L
#define FBODY 126L
#define BBODY 126L
#define SBODY 661L
struct IntuiText
FrontText = {6,0,JAM2,TEXTX,TEXTY,NULL,(UBYTE *)"Front Cutoff: ",NULL},
BackText = {6,0,JAM2,TEXTX,TEXTY,NULL,(UBYTE *)"Rear Cutoff : ",NULL},
ScaleText = {6,0,JAM2,TEXTX,TEXTY,NULL,(UBYTE *)"Scaling Factor: ",NULL};
struct PropInfo
FrontProp = {AUTOKNOB|FREEHORIZ,0,0,FBODY},
BackProp = {AUTOKNOB|FREEHORIZ,0,0,BBODY},
ScaleProp = {AUTOKNOB|FREEHORIZ,0,0,SBODY};
struct Gadget
FrontVGadg = {NULL, GADGX,FGADY, 640,11,
GADGHNONE|GADGIMAGE, RELVERIFY|GADGIMMEDIATE, PROPGADGET,
(APTR)&PropImage1, NULL, &FrontText, NULL, (APTR)&FrontProp, FRONT, NULL},
BackVGadg = {&FrontVGadg, GADGX,BGADY, 640,11,
GADGHNONE|GADGIMAGE, RELVERIFY|GADGIMMEDIATE, PROPGADGET,
(APTR)&PropImage2, NULL, &BackText, NULL, (APTR)&BackProp, BACK, NULL},
ScaleVGadg = {&BackVGadg, GADGX,SGADY, 265,11,
GADGHNONE|GADGIMAGE, RELVERIFY|GADGIMMEDIATE, PROPGADGET,
(APTR)&PropImage3, NULL, &ScaleText, NULL, (APTR)&ScaleProp, SCALE, NULL},
OkayVGadg = {&ScaleVGadg, 285,SGADY+1, 114,9,
GADGHCOMP, RELVERIFY, BOOLGADGET,
(APTR)&MyBorder, NULL, &OkayText, NULL, NULL, OKAY, NULL},
ResetVGadg = {&OkayVGadg, 409,SGADY+1, 114,9,
GADGHCOMP, RELVERIFY, BOOLGADGET,
(APTR)&MyBorder, NULL, &ResetText, NULL, NULL, RESET, NULL},
CancelVGadg = {&ResetVGadg, 533,SGADY+1, 114,9,
GADGHCOMP, RELVERIFY, BOOLGADGET,
(APTR)&MyBorder, NULL, &CancelText, NULL, NULL, CANCEL, NULL};
struct NewWindow ViewNewWindow={
0,50, 656,93, 1,4, GADGETUP|GADGETDOWN|MOUSEBUTTONS,
ACTIVATE|SIMPLE_REFRESH|NOCAREREFRESH|RMBTRAP,
&CancelVGadg,NULL,(UBYTE *)" 4D Navigator View Modifiers",
NULL,NULL,0,0,0,0,CUSTOMSCREEN};
short NewFront, NewBack, NewScale;
ViewRequester()
{
register ULONG Class;
register USHORT GadgetID;
register struct IntuiMessage *msg;
ViewNewWindow.Screen = screen;
if (!(ReqWindow = OpenWindow(&ViewNewWindow))) return;
SetViewProps();
FOREVER {
_WaitPort(ReqWindow->UserPort);
while (msg = _GetMsg(ReqWindow->UserPort)) {
Class = msg->Class;
if (Class == GADGETUP || Class == GADGETDOWN)
GadgetID = ((struct Gadget *)msg->IAddress)->GadgetID;
_ReplyMsg(msg);
switch (Class) {
case GADGETDOWN:
if (GadgetID >= FRONT && GadgetID <= SCALE) {
do {
ReadViewProps();
} while (!(msg = _GetMsg(ReqWindow->UserPort)));
_ReplyMsg(msg);
ReadViewProps();
}
break;
case GADGETUP:
switch (GadgetID) {
case RESET:
SetViewProps();
break;
case OKAY:
if (NewFront == NewBack)
if (NewFront > 0)
NewFront -= 100;
else
NewBack += 100;
if (NewFront < NewBack) {
FrontLimit = NewFront;
BackLimit = NewBack;
} else {
FrontLimit = NewBack;
BackLimit = NewFront;
}
ScaleFactor = NewScale;
case CANCEL:
while (msg=_GetMsg(ReqWindow->UserPort)) _ReplyMsg(msg);
CloseWindow(ReqWindow);
return;
}
}
}
}
}
SetViewProps()
{
NewFront = FrontLimit;
NewBack = BackLimit;
NewScale = ScaleFactor;
NewModifyProp(&FrontVGadg,ReqWindow,0L,(long)(FREEHORIZ|AUTOKNOB),
(ULONG)(((NewFront/100)+258)*127),0L,FBODY,0L,1L);
NewModifyProp(&BackVGadg, ReqWindow,0L,(long)(FREEHORIZ|AUTOKNOB),
(ULONG)(((NewBack /100)+258)*127),0L,BBODY,0L,1L);
NewModifyProp(&ScaleVGadg,ReqWindow,0L,(long)(FREEHORIZ|AUTOKNOB),
(ULONG)((NewScale-1)*661),0L,SBODY,0L,1L);
ShowViewValues();
}
ReadViewProps()
{
NewFront = (((USHORT)FrontProp.HorizPot/127)-258)*100;
NewBack = (((USHORT)BackProp .HorizPot/127)-258)*100;
NewScale = ( (USHORT)ScaleProp.HorizPot/656)+1;
ShowViewValues();
}
ShowViewValues()
{
SPrintF(&FrontText.IText[14],"%6d",NewFront);
SPrintF(&BackText. IText[14],"%6d",NewBack);
SPrintF(&ScaleText.IText[17],"%3d",NewScale);
PrintIText(ReqWindow->RPort,&FrontText,GADGX,FGADY);
PrintIText(ReqWindow->RPort,&BackText, GADGX,BGADY);
PrintIText(ReqWindow->RPort,&ScaleText,GADGX,SGADY);
}
#asm
; A small sprintf() function using the Exec library RawDoFmt() function
public _SysBase,_LVORawDoFmt
public _SPrintF
_SPrintF
movem.l a2/a3,-(sp)
move.l 16(sp),a0
lea.l 20(sp),a1
lea.l put_ch(pc),a2
move.l 12(sp),a3
move.l _SysBase,a6
jsr _LVORawDoFmt(a6)
movem.l (sp)+,a2/a3
rts
put_ch move.b d0,(a3)+
rts
; Stubs for accessing the math libraries
public _MathBase
public _MathTransBase
_LVOSPCeil equ -96
_LVOSPFloor equ -90
_LVOSPDiv equ -84
_LVOSPMul equ -78
_LVOSPSub equ -72
_LVOSPAdd equ -66
_LVOSPNeg equ -60
_LVOSPAbs equ -54
_LVOSPTst equ -48
_LVOSPCmp equ -42
_LVOSPFlt equ -36
_LVOSPFix equ -30
_LVOSPLog10 equ -126
_LVOSPAcos equ -120
_LVOSPAsin equ -114
_LVOSPFieee equ -108
_LVOSPTieee equ -102
_LVOSPSqrt equ -96
_LVOSPPow equ -90
_LVOSPLog equ -84
_LVOSPExp equ -78
_LVOSPTanh equ -72
_LVOSPCosh equ -66
_LVOSPSinh equ -60
_LVOSPSincos equ -54
_LVOSPTan equ -48
_LVOSPCos equ -42
_LVOSPSin equ -36
_LVOSPAtan equ -30
public _SPFix
_SPFix
move.l 4(sp),d0
move.l _MathBase,a6
jmp _LVOSPFix(a6)
public _SPFlt
_SPFlt
move.l 4(sp),d0
move.l _MathBase,a6
jmp _LVOSPFlt(a6)
public _SPCmp
_SPCmp
move.l 4(sp),d1
move.l 12(sp),d0
move.l _MathBase,a6
jmp _LVOSPCmp(a6)
public _SPNeg
_SPNeg
move.l 4(sp),d0
move.l _MathBase,a6
jmp _LVOSPNeg(a6)
public _SPAdd
_SPAdd
move.l 4(sp),d1
move.l 12(sp),d0
move.l _MathBase,a6
jmp _LVOSPAdd(a6)
public _SPSub
_SPSub
move.l 4(sp),d1
move.l 12(sp),d0
move.l _MathBase,a6
jmp _LVOSPSub(a6)
public _SPMul
_SPMul
move.l 4(sp),d1
move.l 12(sp),d0
move.l _MathBase,a6
jmp _LVOSPMul(a6)
public _SPDiv
_SPDiv
move.l 4(sp),d1
move.l 12(sp),d0
move.l _MathBase,a6
jmp _LVOSPDiv(a6)
public _SPTst
_SPTst
move.l 4(sp),d1
move.l _MathBase,a6
jmp _LVOSPTst(a6)
; public _SPAbs
;_SPAbs
; move.l 4(sp),d0
; move.l _MathBase,a6
; jmp _LVOSPAbs(a6)
;
; public _SPCeil
;_SPCeil
; move.l 4(sp),d0
; move.l _MathBase,a6
; jmp _LVOSPCeil(a6)
;
; public _SPFloor
;_SPFloor
; move.l 4(sp),d0
; move.l _MathBase,a6
; jmp _LVOSPFloor(a6)
public _SPSqrt
_SPSqrt
move.l 4(sp),d0
move.l _MathTransBase,a6
jmp _LVOSPSqrt(a6)
public _SPSincos
_SPSincos
move.l 4(sp),d1
move.l 8(sp),d0
move.l _MathTransBase,a6
jmp _LVOSPSincos(a6)
; public _SPSin
;_SPSin
; move.l 4(sp),d0
; move.l _MathTransBase,a6
; jmp _LVOSPSin(a6)
;
; public _SPCos
;_SPCos
; move.l 4(sp),d0
; move.l _MathTransBase,a6
; jmp _LVOSPCos(a6)
;
; public _SPTan
;_SPTan
; move.l 4(sp),d0
; move.l _MathTransBase,a6
; jmp _LVOSPTan(a6)
;
; public _SPAsin
;_SPAsin
; move.l 4(sp),d0
; move.l _MathTransBase,a6
; jmp _LVOSPAsin(a6)
public _SPAcos
_SPAcos
move.l 4(sp),d0
move.l _MathTransBase,a6
jmp _LVOSPAcos(a6)
; public _SPAtan
;_SPAtan
; move.l 4(sp),d0
; move.l _MathTransBase,a6
; jmp _LVOSPAtan(a6)
;
; public _SPSinh
;_SPSinh
; move.l 4(sp),d0
; move.l _MathTransBase,a6
; jmp _LVOSPSinh(a6)
;
; public _SPCosh
;_SPCosh
; move.l 4(sp),d0
; move.l _MathTransBase,a6
; jmp _LVOSPCosh(a6)
;
; public _SPTanh
;_SPTanh
; move.l 4(sp),d0
; move.l _MathTransBase,a6
; jmp _LVOSPTanh(a6)
;
; public _SPExp
;_SPExp
; move.l 4(sp),d0
; move.l _MathTransBase,a6
; jmp _LVOSPExp(a6)
;
; public _SPLog
;_SPLog
; move.l 4(sp),d0
; move.l _MathTransBase,a6
; jmp _LVOSPLog(a6)
;
; public _SPPow
;_SPPow
; move.l 4(sp),d1
; move.l 12(sp),d0
; move.l _MathTransBase,a6
; jmp _LVOSPPow(a6)
;
; public _SPLog10
;_SPLog10
; move.l 4(sp),d0
; move.l _MathTransBase,a6
; jmp _LVOSPLog10(a6)
;
; public _SPTieee
;_SPTieee
; move.l 4(sp),d0
; move.l _MathTransBase,a6
; jmp _LVOSPTieee(a6)
;
; public _SPFieee
;_SPFieee
; move.l 4(sp),d0
; move.l _MathTransBase,a6
; jmp _LVOSPFieee(a6)
#endasm
#if TIMING
PrintTime(what,start,finish)
char *what;
long *start,*finish;
{
long dd;
register long hh, mm, ss, xx; /*** d4, d5, d6, d7 ***/
if (start[2] > finish[2]) { finish[1]--; finish[2] += 3000; }
if (start[1] > finish[1]) { finish[0]--; finish[1] += 1440; }
dd=finish[0]-start[0]; mm=finish[1]-start[1]; xx=finish[2]-start[2];
#asm
move.l d5,d4 ; hh = mm/60
divu #60,d4
ext.l d4
move.w d4,d0 ; mm -= hh*60
mulu #60,d0
sub.l d0,d5
move.l d7,d6 ; ss = xx/50
divu #50,d6
ext.l d6
move.w d6,d0 ; xx -= ss*50
mulu #50,d0
sub.l d0,d7
asl.l #1,d7 ; xx *= 2
#endasm
PrintF("%s: %ld-%02ld:%02ld:%02ld.%02ld\n",what,dd,hh,mm,ss,xx);
}
#endif
#if DEBUG
dump_screen_plot()
{
register short plong,lat,elong;
register long index;
register short *toplot, *toget;
long num;
short firstx, firsty;
short plot_buf[(SEGMENTS+1)*2];
long file,_Open();
if (!(file = _Open("ram:lines.dat",1006L))) return;
toplot = plot_buf;
toget = e2d;
firstx = DONT_PLOT;
if ((toplot[num=0] = toget[0]) != DONT_PLOT) {
firstx = toplot[0]; firsty = toplot[1] = toget[1]; num=2;
}
for (elong=2; elong<SEGMENTS*2; elong+=2)
if ((toplot[num] = toget[elong]) != DONT_PLOT) {
toplot[++num] = toget[elong+1]; num++;
} else {
if (num >= 4) {
plot_dump(file,"EQUATOR",0,0,elong/2,num,toplot);
}
num = 0;
}
if (num >= 2 && firstx != DONT_PLOT) {
toplot[num++] = firstx; toplot[num++] = firsty;
}
if (num >= 4) {
plot_dump(file,"EQUATOR",0,0,elong/2,num,toplot);
}
toget = p2d;
firstx = DONT_PLOT;
if ((toplot[num=0] = toget[0]) != DONT_PLOT) {
firstx = toplot[0]; firsty = toplot[1] = toget[1]; num=2;
}
for (plong=2; plong<SEGMENTS*2; plong+=2)
if ((toplot[num] = toget[plong]) != DONT_PLOT) {
toplot[++num] = toget[plong+1]; num++;
} else {
if (num >= 4) {
plot_dump(file,"POLAR RING",plong/2,0,0,num,toplot);
}
num = 0;
}
if (num >= 2 && firstx != DONT_PLOT) {
toplot[num++] = firstx; toplot[num++] = firsty;
}
if (num >= 4) {
plot_dump(file,"POLAR RING",plong/2,0,0,num,toplot);
}
toget = x2d;
for (lat=0; lat<LATRNG; lat++)
for (elong=0; elong<SEGMENTS; elong++) {
firstx = DONT_PLOT;
if ((toplot[num=0] = toget[index=INDX(0,lat,elong)*2]) != DONT_PLOT) {
firstx = toplot[0]; firsty = toplot[1] = toget[index+1]; num=2;
}
for (plong=1; plong<SEGMENTS; plong++)
if ((toplot[num]=toget[index=INDX(plong,lat,elong)*2])!=DONT_PLOT) {
toplot[++num] = toget[index+1]; num++;
} else {
if (num >= 4) {
plot_dump(file,"CIRCUMPOLAR",plong,lat+1,elong,num,toplot);
}
num = 0;
}
if (num >= 2 && firstx != DONT_PLOT) {
toplot[num++] = firstx; toplot[num++] = firsty;
}
if (num >= 4) {
plot_dump(file,"CIRCUMPOLAR",plong,lat+1,elong,num,toplot);
}
}
for (lat=0; lat<LATRNG; lat++)
for (plong=0; plong<SEGMENTS; plong++) {
firstx = DONT_PLOT;
if ((toplot[num=0] = toget[index=INDX(plong,lat,0)*2]) != DONT_PLOT) {
firstx = toplot[0]; firsty = toplot[1] = toget[index+1]; num=2;
}
for (elong=1; elong<SEGMENTS; elong++)
if ((toplot[num]=toget[index=INDX(plong,lat,elong)*2])!=DONT_PLOT) {
toplot[++num] = toget[index+1]; num++;
} else {
if (num >= 4) {
plot_dump(file,"CIRCUMEQUATORIAL",plong,lat+1,elong,num,toplot);
}
num = 0;
}
if (num >= 2 && firstx != DONT_PLOT) {
toplot[num++] = firstx; toplot[num++] = firsty;
}
if (num >= 4) {
plot_dump(file,"CIRCUMEQUATORIAL",plong,lat+1,elong,num,toplot);
}
}
for (elong=0; elong<SEGMENTS; elong++)
for (plong=0; plong<SEGMENTS; plong++) {
num = 0;
if (!(elong&1))
if ((toplot[0] = e2d[plong*2]) != DONT_PLOT) {
toplot[1] = e2d[plong*2+1]; num=2;
}
for (lat=0; lat<LATRNG; lat++)
if ((toplot[num]=toget[index=INDX(plong,lat,elong)*2])!=DONT_PLOT) {
toplot[++num] = toget[index+1]; num++;
} else {
if (num >= 4) {
plot_dump(file,"LONGITUDE LINES",plong,lat+1,elong,num,toplot);
}
num = 0;
}
if (!(plong&1))
if ((toplot[num] = p2d[elong*2]) != DONT_PLOT) {
toplot[++num] = p2d[elong*2+1]; num++;
}
if (num >= 4) {
plot_dump(file,"LONGITUDE LINES",plong,lat+1,elong,num,toplot);
}
}
_Close(file);
}
plot_dump(file,label,plong,lat,elong,num,toplot)
long file;
char *label;
short plong,lat,elong;
long num;
short *toplot;
{
long i;
FPrintF(file,"%s\nplong = %d lat = %d elong = %d num = %ld\n",
label,plong*INTERVAL,lat*INTERVAL,elong*INTERVAL,num);
for (i=0; i < num; i+=2)
FPrintF(file,"%5d\t%5d\n",toplot[i],toplot[i+1]);
FPrintF(file,"\n");
}
dump_coordinates(all)
int all;
{
short plong,lat,elong;
long file, _Open();
if (!(file = _Open("ram:coord.dat",1006L))) return;
for (plong=0; plong<SEGMENTS; plong++)
for (lat=0; lat<LATRNG; lat++)
for (elong=0; elong<SEGMENTS; elong++)
if (all || x2d[INDX(plong,lat,elong)*2+X] != DONT_PLOT)
FPrintF(file,
"x[%3d][%2d][%3d] = (%6d,%6d,%6d,%6d) (%6d,%6d,%6d) (%6d,%6d)\n",
plong*INTERVAL, (lat+1)*INTERVAL, elong*INTERVAL,
x4d[INDX(plong,lat,elong)*4+X], x4d[INDX(plong,lat,elong)*4+Y],
x4d[INDX(plong,lat,elong)*4+Z], x4d[INDX(plong,lat,elong)*4+W],
x3d[INDX(plong,lat,elong)*3+X], x3d[INDX(plong,lat,elong)*3+Y],
x3d[INDX(plong,lat,elong)*3+Z],
x2d[INDX(plong,lat,elong)*2+X], x2d[INDX(plong,lat,elong)*2+Y]);
for (plong=0; plong<SEGMENTS; plong++)
if (all || p2d[plong*2+X] != DONT_PLOT)
FPrintF(file, "p[%3d] = (%6d,%6d,%6d,%6d) (%6d,%6d,%6d) (%6d,%6d)\n",
plong*INTERVAL,
p4d[plong*4+X], p4d[plong*4+Y], p4d[plong*4+Z], p4d[plong*4+W],
p3d[plong*3+X], p3d[plong*3+Y], p3d[plong*3+Z],
p2d[plong*2+X], p2d[plong*2+Y]);
for (elong=0; elong<SEGMENTS; elong++)
if (all || e2d[elong*2+X] != DONT_PLOT)
FPrintF(file, "e[%3d] = (%6d,%6d,%6d,%6d) (%6d,%6d,%6d) (%6d,%6d)\n",
elong*INTERVAL,
e4d[elong*4+X], e4d[elong*4+Y], e4d[elong*4+Z], e4d[elong*4+W],
e3d[elong*3+X], e3d[elong*3+Y], e3d[elong*3+Z],
e2d[elong*2+X], e2d[elong*2+Y]);
_Close(file);
}
#endif
#if TIMING | DEBUG
#asm
; FUNCTION IMPLEMENTATION
; void PrintF(fmt_str,args...) FPrintF(Output(),fmt_str,args...)
; void FPrintF(fh,fmt_str,args...)
;
; These functions have no return value, unlike the standard 'C' versions
; that return the number of items matched in the format string.
;
; Note that PrintF and FPrintF use stack space for buffering the resulting
; string. The length of the resulting string is set up below to be limited
; to < 256 characters. If longer strings are needed, increase the buffer
; size (ResBuf), but beware of stack overflow when doing so.
;Globals
public _SysBase,_DOSBase
public _LVORawDoFmt,_LVOWrite,_LVOOutput
ResBuf equ 256
public _PrintF
_PrintF
move.l _DOSBase,a6 ; get file handle of current output
jsr _LVOOutput(a6) ; using Output()
move.l (sp),-(sp) ; duplicate return address
move.l d0,4(sp) ; put file handle "under" it
; fall into FPrintF
public _FPrintF
_FPrintF
movem.l a2/a3,-(sp) ; don't need to save registers d0-3,a0-1,a6
move.l 16(sp),a0 ; format string
lea.l 20(sp),a1 ; data stream
lea.l put_char(pc),a2 ; output procedure called by RawDoFmt
lea.l -ResBuf(sp),sp ; allocate some stack space where
move.l sp,a3 ; put_ch will put characters from RawDoFmt
move.l _SysBase,a6 ; do the magic
jsr _LVORawDoFmt(a6) ; using RawDoFmt()
move.l ResBuf+12(sp),d1 ; output file handle
move.l sp,d2 ; the result string is on the stack
moveq #0,d3
move.w str_len,d3 ; string length
beq.s 1$ ; ignore a zero length string
move.l _DOSBase,a6 ; output the results
jsr _LVOWrite(a6) ; using Write()
1$ move.w #-1,str_len ; reset for next time
lea.l ResBuf(sp),sp ; release stack space
movem.l (sp)+,a2/a3 ; restore registers
rts ; all done
; length of the output string minus the terminating null
dseg
public str_len
str_len dc.w -1
cseg
far data
put_char
addq.w #1,str_len ; add 1 to string length
near data
move.b d0,(a3)+ ; this "procedure" stuffs the characters from
rts ; RawDoFmt into the destination buffer
#endasm
#endif